

using System;
using System.Numerics;

namespace NodeBasedSkillEditor.Model.Node.RT
{
    public class Node_Comparison_RT : RT_Node
    {
        public RT_SingleValuePort Mode_RT;

        public RT_SingleValuePort Value1_RT;

        public RT_SingleValuePort Value2_RT;

        public RT_SingleValuePort Result_RT;

        public Node_Comparison_RT(Node_Comparison sourceData, RT_DAG parentDag) : base(sourceData, parentDag)
        {
            Value1_RT = new RT_SingleValuePort(EPortIOType.Input, sourceData.Value1, this);

            Value2_RT = new RT_SingleValuePort(EPortIOType.Input, sourceData.Value2, this);

            Mode_RT = new RT_SingleValuePort(EPortIOType.Input, sourceData.Mode, this);

            Result_RT = new RT_SingleValuePort(EPortIOType.Output, sourceData.Result, this);
            Result_RT.OnGetValue = GetResult;
        }

        public AValue GetResult(DAG_Executor executor)
        {
            var valueType = Value1_RT.SourceValue.ValueType;
            var compMode = (ECompMode)Mode_RT.GetValue(executor).ToEnum().Item2;
            switch (valueType)
            {
                case AValue.EValueType.Unknown: break;
                case AValue.EValueType.Boolean:
                    bool b1 = Value1_RT.GetValue(executor).ToBoolean().Item2;
                    bool b2 = Value2_RT.GetValue(executor).ToBoolean().Item2;
                    bool bResult = CompareBool(b1, b2, compMode);
                    Result_RT.SourceValue.SetBoolean(bResult);
                    break;

                case AValue.EValueType.Integer:
                    int i1 = Value1_RT.GetValue(executor).ToInteger().Item2;
                    int i2 = Value2_RT.GetValue(executor).ToInteger().Item2;
                    bool iResult = CompareInt(i1, i2, compMode);
                    Result_RT.SourceValue.SetBoolean(iResult);
                    break;

                case AValue.EValueType.Scalar:
                    float f1 = Value1_RT.GetValue(executor).ToScalar().Item2;
                    float f2 = Value2_RT.GetValue(executor).ToScalar().Item2;
                    bool fResult = CompareFloat(f1, f2, compMode);
                    Result_RT.SourceValue.SetBoolean(fResult);
                    break;

                case AValue.EValueType.Vector2:
                    Vector2 v2a = Value1_RT.GetValue(executor).ToVector2().Item2;
                    Vector2 v2b = Value2_RT.GetValue(executor).ToVector2().Item2;
                    bool v2Result = CompareVector2(v2a, v2b, compMode);
                    Result_RT.SourceValue.SetBoolean(v2Result);
                    break;

                case AValue.EValueType.Vector3:
                    Vector3 v3a = Value1_RT.GetValue(executor).ToVector3().Item2;
                    Vector3 v3b = Value2_RT.GetValue(executor).ToVector3().Item2;
                    bool v3Result = CompareVector3(v3a, v3b, compMode);
                    Result_RT.SourceValue.SetBoolean(v3Result);
                    break;

                case AValue.EValueType.String:
                    string s1 = Value1_RT.GetValue(executor).ToString();
                    string s2 = Value2_RT.GetValue(executor).ToString();
                    bool sResult = CompareString(s1, s2, compMode);
                    Result_RT.SourceValue.SetBoolean(sResult);
                    break;

                case AValue.EValueType.Enum:
                    Enum e1 = Value1_RT.GetValue(executor).ToEnum().Item2;
                    Enum e2 = Value2_RT.GetValue(executor).ToEnum().Item2;
                    bool eResult = CompareEnum(e1, e2, compMode);
                    Result_RT.SourceValue.SetBoolean(eResult);
                    break;

                default:
                    break;
            }
            return Result_RT.SourceValue;
        }

        bool CompareBool(bool v1, bool v2, ECompMode compMode)
        {
            switch (compMode)
            {
                case ECompMode.LessThan:
                    return v1 == false && v2 == true;
                case ECompMode.LessThanOrEqualTo:
                    return true;
                case ECompMode.EqualTo:
                    return v1 == v2;
                case ECompMode.BiggerThan:
                    return v1 == true && v2 == false;
                case ECompMode.BiggerThanOrEqualTo:
                    return true;
                case ECompMode.NotEqualTo:
                    return v1 != v2;
                default: return false;
            }
        }

        bool CompareInt(int v1, int v2, ECompMode compMode)
        {
            switch (compMode)
            {
                case ECompMode.LessThan:
                    return v1 < v2;

                case ECompMode.LessThanOrEqualTo:
                    return v1 <= v2;

                case ECompMode.EqualTo:
                    return v1 == v2;

                case ECompMode.BiggerThan:
                    return v1 > v2;

                case ECompMode.BiggerThanOrEqualTo:
                    return v1 >= v2;

                case ECompMode.NotEqualTo:
                    return v1 != v2;

                default: return false;
            }
        }

        bool CompareFloat(float v1, float v2, ECompMode compMode)
        {
            switch (compMode)
            {
                case ECompMode.LessThan:
                    return v1 < v2;

                case ECompMode.LessThanOrEqualTo:
                    return v1 <= v2;

                case ECompMode.EqualTo:
                    return v1 == v2;

                case ECompMode.BiggerThan:
                    return v1 > v2;

                case ECompMode.BiggerThanOrEqualTo:
                    return v1 >= v2;

                case ECompMode.NotEqualTo:
                    return v1 != v2;

                default: return false;
            }
        }

        bool CompareVector2(Vector2 vec1, Vector2 vec2, ECompMode compMode)
        {
            float v1 = vec1.LengthSquared();
            float v2 = vec2.LengthSquared();

            switch (compMode)
            {
                case ECompMode.LessThan:
                    return v1 < v2;

                case ECompMode.LessThanOrEqualTo:
                    return v1 <= v2;

                case ECompMode.EqualTo:
                    return v1 == v2;

                case ECompMode.BiggerThan:
                    return v1 > v2;

                case ECompMode.BiggerThanOrEqualTo:
                    return v1 >= v2;

                case ECompMode.NotEqualTo:
                    return v1 != v2;

                default: return false;
            }
        }

        bool CompareVector3(Vector3 vec1, Vector3 vec2, ECompMode compMode)
        {
            float v1 = vec1.LengthSquared();
            float v2 = vec2.LengthSquared();

            switch (compMode)
            {
                case ECompMode.LessThan:
                    return v1 < v2;

                case ECompMode.LessThanOrEqualTo:
                    return v1 <= v2;

                case ECompMode.EqualTo:
                    return v1 == v2;

                case ECompMode.BiggerThan:
                    return v1 > v2;

                case ECompMode.BiggerThanOrEqualTo:
                    return v1 >= v2;

                case ECompMode.NotEqualTo:
                    return v1 != v2;

                default: return false;
            }
        }

        bool CompareString(string str1, string str2, ECompMode compMode)
        {
            int v1 = str1.Length;
            int v2 = str2.Length;

            switch (compMode)
            {
                case ECompMode.LessThan:
                    return v1 < v2;

                case ECompMode.LessThanOrEqualTo:
                    return v1 <= v2;

                case ECompMode.EqualTo:
                    return str1 == str2;

                case ECompMode.BiggerThan:
                    return v1 > v2;

                case ECompMode.BiggerThanOrEqualTo:
                    return v1 >= v2;

                case ECompMode.NotEqualTo:
                    return str1 != str2;

                default: return false;
            }
        }

        bool CompareEnum(Enum e1, Enum e2, ECompMode compMode)
        {
            int v1 = Convert.ToInt32(e1);
            int v2 = Convert.ToInt32(e2);

            switch (compMode)
            {
                case ECompMode.LessThan:
                    return v1 < v2;

                case ECompMode.LessThanOrEqualTo:
                    return v1 <= v2;

                case ECompMode.EqualTo:
                    return v1 == v2;

                case ECompMode.BiggerThan:
                    return v1 > v2;

                case ECompMode.BiggerThanOrEqualTo:
                    return v1 >= v2;

                case ECompMode.NotEqualTo:
                    return v1 != v2;

                default: return false;
            }
        }
    }
}